package com.dooioo.pns.api.job;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dooioo.pns.api.leancloud.LData;
import com.dooioo.pns.api.leancloud.LeanCloudRequestUtils;
import com.dooioo.pns.api.leancloud.Push;
import com.dooioo.pns.api.leancloud.Where;
import com.dooioo.pns.api.utils.HttpClientUtil;
import com.dooioo.pns.business.service.*;
import com.dooioo.pns.business.service.v2.BusinessSideUnDisturbService;
import com.dooioo.pns.core.config.BaseConfiguration;
import com.dooioo.pns.entity.model.BusinessSide;
import com.dooioo.pns.entity.model.DeviceInfo;
import com.dooioo.pns.entity.model.DeviceLogoutTask;
import com.dooioo.pns.entity.model.Message;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.ProtocolException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * PackageName:com.dooioo.pns.api.job
 * Author: Jerry.hu
 * Create: Jerry.hu (2015-07-30 下午4:28)
 * Description:
 * To change this template use File | Settings | File Templates.
 */
@Component
public class SyncLeanCloud {
	@Autowired
	private LeanCloudRequestUtils leanCloudRequestUtils;
	@Autowired
	private DeviceInfoService deviceInfoService;
	@Autowired
	private AppInfoService appInfoService;
	@Autowired
	private DeviceLogoutTaskService deviceLogoutTaskService;
	@Autowired
	private MessageService messageService;
	@Autowired
	private BusinessSideUnDisturbService businessSideUnDisturbService;
	@Autowired
	private BusinessSideService businessSideService;

	/**
	 * 1、定时扫描踢人信息，并且处理踢人信息
	 * 2、定时扫描踢人信息里，注册失败的信息,进行重新注册
	 * 3、定时扫描踢人成功，注销设备，本地pns 注销，leanCloud同样注销
	 */
	@Scheduled(cron = "0/5 * 05-23 * * *")
	public void syncLogout(){
		List<DeviceLogoutTask> deviceLogoutTasks = deviceLogoutTaskService.getLogoutTask();
		if(deviceLogoutTasks.size() > 0){
			for (DeviceLogoutTask deviceLogoutTask : deviceLogoutTasks){
				Push push = new Push();
				Where where = new Where();
				LData lData = new LData();
				lData.setAlert(deviceLogoutTask.getLogoutMsg());
				lData.setBusinessId("1002");
				where.setUuid(deviceLogoutTask.getPlatform(), deviceLogoutTask.getUuid());
				push.setData(lData);
				push.setWhere(where);
				//发送踢出消息
				leanCloudRequestUtils.logout(getFormat(deviceLogoutTask),push, appInfoService.getHeaderMap(deviceLogoutTask.getAppId()));
			}
		}
		List<DeviceLogoutTask> logoutRegisters = deviceLogoutTaskService.getLogoutTaskRegisters();
		for(DeviceLogoutTask deviceLogoutTask : logoutRegisters){
			//发送注册服务
			leanCloudRequestUtils.register(getFormat(deviceLogoutTask),appInfoService.getHeaderMap(deviceLogoutTask.getAppId()),true);
		}
		List<DeviceLogoutTask> logoutTaskList = deviceLogoutTaskService.getClearTask();
		for (DeviceLogoutTask deviceLogoutTask : logoutTaskList){
			Map<String,String> headerMap = appInfoService.getHeaderMap(deviceLogoutTask.getAppId());
			//发送注销信息
			if(getNotificationStatus(deviceLogoutTask.getMessageId().trim(),headerMap).equals("done")){
				leanCloudRequestUtils.logoff(getFormat(deviceLogoutTask),appInfoService.getHeaderMap(deviceLogoutTask.getAppId()),true);
			}
		}
	}


	/**
	 * 定时扫描，注册失败的活跃设备信息，并且进行重新注册
	 */
	@Scheduled(cron = "0/2 * 05-23 * * *")
	public void syncRegisterDeviceInfo(){
		List<DeviceInfo> deviceInfos = deviceInfoService.getRegistersFail();
		if(deviceInfos.size() > 0){
			for (DeviceInfo deviceInfo : deviceInfos){
				leanCloudRequestUtils.register(deviceInfo, appInfoService.getHeaderMap(deviceInfo.getAppId()), false);
			}
		}else{
			List<DeviceInfo> registersFails = deviceInfoService.getLogoffFail();
			for(DeviceInfo deviceInfo : registersFails){
				//发送注册服务
				leanCloudRequestUtils.logoff(deviceInfo, appInfoService.getHeaderMap(deviceInfo.getAppId()), false);
			}
		}
	}


	/**
	 * 定时扫描，消息发送失败的信息
	 */
	@Scheduled(cron = "0 0/2 05-23 * * *")
	public void syncSendMsg(){
		List<Message> messagesList = messageService.getSendFailList();
		for (Message message : messagesList){
			BusinessSide businessSide = businessSideService.getBean(message.getBusinessId());
			sendMsg(getRecipients(message),message,businessSide);
		}
	}

	/**
	 * 发生消息 函数
	 * @param userCodes 接收人集合
	 * @param message 消息对象
	 * @param businessSide 业务方实体
	 */
	private void sendMsg(List<String> userCodes,Message message,BusinessSide businessSide){
		List<String> unDisturbUserCodes = businessSideUnDisturbService.getUnDisturb(message.getBusinessId(), userCodes);
		userCodes.removeAll(unDisturbUserCodes);
		if(userCodes.size() >0) {
			Push push = getPush(message,true,businessSide);
			push.setChannels(userCodes.toArray(new String[userCodes.size()]));
			leanCloudRequestUtils.send(message.getId(),push,appInfoService.getHeaderMap(message.getAppId()));
		}
		if(unDisturbUserCodes.size() >0){
			Push push = getPush(message,false,businessSide);
			push.setChannels(unDisturbUserCodes.toArray(new String[unDisturbUserCodes.size()]));
			leanCloudRequestUtils.send(message.getId(),push,appInfoService.getHeaderMap(message.getAppId()));
		}
	}

	/**
	 * 将注销设备 格式化为 标准的设备实体
	 * @param deviceLogoutTask
	 * @return
	 */
	public DeviceInfo getFormat(DeviceLogoutTask deviceLogoutTask){
		DeviceInfo deviceInfo = new DeviceInfo();
		deviceInfo.setId(deviceLogoutTask.getId());
		deviceInfo.setAppId(deviceLogoutTask.getAppId());
		deviceInfo.setUuid(deviceLogoutTask.getUuid());
		deviceInfo.setPlatform(deviceLogoutTask.getPlatform());
		deviceInfo.setDeviceId(deviceLogoutTask.getDeviceId());
		return deviceInfo;
	}

	/**
	 * 获取接收人信息
	 * @param message 消息实体
	 * @return 接收人集合
	 */
	public List<String> getRecipients(Message message){
		String recipient = message.getRecipients();
		recipient = recipient.replace("[","").replace("]","");
		String [] recipients = recipient.split(",");
		return Arrays.asList(recipients);
	}

	/**
	 * 获取发送的实体
	 * @param message
	 * @return
	 */
	private Push getPush(Message message,boolean disturb,BusinessSide businessSide){
		Push push = new Push();
		LData lData = new LData();
		if(businessSide.isShow()){
			if(!StringUtils.isBlank(message.getRemark())){
				if(message.getRemark().length() > 30){
					lData.setAlert(businessSide.getName()+":"+message.getRemark().substring(0,30)+"...");
				}else{
					lData.setAlert(businessSide.getName()+":"+message.getRemark()+"...");
				}
			} else {
				lData.setAlert(message.getPrompt());
			}
		}else {
			lData.setAlert(message.getPrompt());
		}
		lData.setBusinessId(String.valueOf(message.getBusinessId()));
		lData.setExtensionInfo(message.getExtensionInfo());
		lData.setTouchdown(String.valueOf(message.getTouchdown()));
		lData.setCategory(String.valueOf(message.getCategory()));
		if(!disturb){
			lData.setSound("");
		}
		push.setData(lData);
		return push;
	}

	/**
	 * 根据消息的id 获取消息的发送状态
	 * @param messageId leanCloud 通知id
	 * @param headerMap leanCloud 请求头部参数
	 * @return 通知的状态
	 */
	private String getNotificationStatus(String messageId,Map<String,String> headerMap){
		try {
			String result =  HttpClientUtil.getInstance().doGetResult(BaseConfiguration.getInstance().getLeanNotificationUrl() + "/" +messageId, new HashMap<>(),headerMap);
			JSONObject jsonObject = JSON.parseObject(result);
			Object object = jsonObject.get("status");
			if(object != null){
				return object.toString();
			}else{
				return "";
			}
		} catch (IOException | ProtocolException | ConfigurationException e) {
			e.printStackTrace();
			return "";
		}
	}

}
